package rewardservice

import (
	"context"
	"fmt"
	"games.com/server/internal/pkg/config"
	_ "github.com/go-sql-driver/mysql"
	"github.com/jmoiron/sqlx"
)

var (
	insertRewardsSQL    = `INSERT INTO rewards (gm, player, reward, datetime) VALUES (?, ?, ?, ?)`
	deleteRewardsSQL    = `DELETE FROM rewards WHERE id = ?`
	updateRewardsSQL    = `UPDATE rewards SET gm = ?, player = ?, reward = ?, datetime = ? WHERE id = ?`
	selectRewardsCntSQL = `SELECT count(1) FROM rewards`
	selectRewardsSQL    = `SELECT id, gm, player, reward, datetime FROM rewards LIMIT ?, ?`
	selectRewardByIDSQL = `SELECT id, gm, player, reward, datetime FROM rewards WHERE id = ?`
)

type rewardDAO struct {
	db *sqlx.DB
}

func NewRewardDAO(config *config.Config) (*rewardDAO, error) {
	ad := &rewardDAO{}

	db, err := sqlx.Connect("mysql", config.Dsn)
	if err != nil {
		return nil, fmt.Errorf("failed to open mysql connection, dsn:%s, err:%w", config.Dsn, err)
	}

	ad.db = db
	return ad, nil
}

func (ad *rewardDAO) InsertRewards(ctx context.Context, reward *Reward) error {
	result, err := ad.db.ExecContext(ctx, insertRewardsSQL, reward.Gm, reward.Player, reward.Reward, reward.DateTime)
	if err != nil {
		return err
	}

	ID, err := result.LastInsertId()
	if err != nil {
		return err
	}

	reward.ID = int32(ID)

	return nil
}

func (ad *rewardDAO) DeleteRewards(ctx context.Context, ID int32) error {
	_, err := ad.db.ExecContext(ctx, deleteRewardsSQL, ID)
	if err != nil {
		return err
	}

	return nil
}

func (ad *rewardDAO) UpdateRewards(ctx context.Context, reward *Reward) error {
	_, err := ad.db.ExecContext(ctx, updateRewardsSQL, reward.Gm, reward.Player, reward.Reward, reward.DateTime, reward.ID)
	if err != nil {
		return err
	}

	return nil
}

func (ad *rewardDAO) QueryRewardsCnt(ctx context.Context) (int32, error) {
	var cnt int32

	err := ad.db.GetContext(ctx, &cnt, selectRewardsCntSQL)
	if err != nil {
		return cnt, err
	}

	return cnt, nil
}

func (ad *rewardDAO) QueryRewards(ctx context.Context, start, offset int32) ([]*Reward, error) {
	var rewards []*Reward

	err := ad.db.SelectContext(ctx, &rewards, selectRewardsSQL, start, offset)
	if err != nil {
		return nil, err
	}

	return rewards, nil
}

func (ad *rewardDAO) QueryRewardByID(ctx context.Context, id int32) (*Reward, error) {
	var reward Reward

	err := ad.db.GetContext(ctx, &reward, selectRewardByIDSQL, id)
	if err != nil {
		return nil, err
	}

	return &reward, nil
}
